import * as d3 from "d3";
interface WaveOption {
  el: HTMLElement;
  strokeStyle: string;
  waveNum?: number;
  wavePre?: number;
}
export class WaveView {
  currentX = 0; //当前X坐标
  currentY = 0; //当前Y坐标
  lastX = 0; //上次X坐标
  lastY = 0; //上次Y坐标
  clearGap = 15; // 橡皮檫宽度

  width = 0;
  height = 0;
  ctx: any;
  queue: any[] = []; // 队列
  strokeStyle = "#0f0"; //线条默认颜色

  private grid_width = 2; // 每一个小网格的宽高
  step = 0; // 每次画几个点

  frameSize = 0; //1秒多少个点
  drawInterval = 20;
  loopTimer: NodeJS.Timeout | null = null;
  // xScale;
  yScale: any;
  waveNum: number;
  waveHeight: number;
  isStop = false;
  /**
   * @param el DOM
   * @param strokeStyle 线的颜色
   */
  constructor({ el, strokeStyle, waveNum = 5, wavePre = 0.9 }: WaveOption) {
    const canvas = d3
      .select(el)
      .append("canvas")
      .attr("width", el.clientWidth)
      .attr("height", el.clientHeight)
      .style("background", "transparent")
      .style("position", "absolute")
      .style("top", 0)
      .style("left", 0)
      .style("z-index", 2)
      .node();
    this.width = el.clientWidth;
    this.height = el.clientHeight;
    this.waveHeight = el.offsetHeight * wavePre;
    this.ctx = canvas?.getContext("2d");
    this.ctx.imageSmoothingEnabled = true;
    this.ctx.imageSmoothingQuality = "high";
    this.lastY = this.height / 2;

    this.strokeStyle = strokeStyle;
    this.waveNum = waveNum;
    document.addEventListener("visibilitychange", () => {
      if (document.hidden) {
        // 页面已经切换到后台
        console.log("切换到后台");
        this.isStop = true;
      } else {
        // 页面已经切换到前台
        console.log("切换到前台");
        this.isStop = false;
      }
    });
  }

  draw = () => {
    // 更新心电图
    this.ctx.beginPath();
    this.ctx.lineWidth = 1;
    this.ctx.strokeStyle = this.strokeStyle;
    this.ctx.clearRect(this.lastX, 0, this.clearGap, this.height);
    for (let i = 0; i < this.step; i++) {
      if (this.queue.length === 0) {
        this.currentY = this.height / 2;
      } else {
        this.currentY = this.yScale(this.queue.shift());
      }
      this.ctx.moveTo(this.lastX, this.lastY);
      this.ctx.lineTo(this.currentX, this.currentY);
      this.lastX = this.currentX;
      this.lastY = this.currentY;

      this.currentX += this.width / (this.waveNum * this.frameSize);

      if (this.currentX >= this.width) {
        this.currentX = 0;
        this.lastX = 0;
      }
    }
    this.ctx.stroke();
  };
  loop = () => {
    if (this.queue.length) {
      this.draw();
      this.loopTimer = setTimeout(this.loop, this.drawInterval);
    } else {
      clearTimeout(this.loopTimer!);
      this.loopTimer = null;
    }
  };
  addData = (arr: string | any[]) => {
    if (!this.yScale) {
      // this.xScale = d3.scaleLinear().domain([0, 60000]).range([0, this.width]);
      this.yScale = d3
        .scaleLinear()
        .domain([-d3.max(arr), d3.max(arr)])
        .range([this.waveHeight, this.height - this.waveHeight]);
    }
    if (!this.isStop) {
      this.queue.push(...arr);
      this.frameSize = arr.length;
      this.step = Math.floor((this.queue.length / 1000) * this.drawInterval);
      if (!this.loopTimer) {
        this.loop();
      }
    }
  };
  close = () => {
    this.queue = [];
    clearTimeout(this.loopTimer!);
    this.loopTimer = null;
    this.ctx.clearRect(0, 0, this.width, this.height);
  };
  drawGrid = (el: HTMLElement) => {
    const canvas = d3
      .select(el)
      .append("canvas")
      .attr("width", el.clientWidth)
      .attr("height", el.clientHeight)
      .style("background", "transparent")
      .style("position", "absolute")
      .style("top", 0)
      .style("left", 0)
      .style("z-index", 1)
      .node();
    const width = el.clientWidth;
    const height = el.clientHeight;
    const ctx = canvas?.getContext("2d");
    let hLineNum = parseInt(`${height}/ ${this.grid_width}`);
    let vLineNum = parseInt(`${width}/ ${this.grid_width}`);
    if (!ctx) return;
    ctx.beginPath();
    ctx.lineWidth = 2;
    ctx.strokeStyle = "#062626"; //"#FF7F50";
    for (let i = 0; i <= vLineNum; i += 15) {
      ctx.moveTo(i * this.grid_width, 0);
      ctx.lineTo(i * this.grid_width, height);
      ctx.stroke();
    }
    ctx.beginPath();
    ctx.lineWidth = 0;
    ctx.strokeStyle = "#062626"; //"#FF7F50";
    for (let i = 0; i <= hLineNum; i += 15) {
      ctx.moveTo(0, i * this.grid_width);
      ctx.lineTo(width, i * this.grid_width);
      ctx.stroke();
    }
  };
}
